package com.beiding.delaytask.fram.impl;

import com.beiding.delaytask.entity.TimeTask;
import com.beiding.delaytask.fram.DelaySender;
import com.beiding.delaytask.fram.Time;
import com.beiding.delaytask.fram.TimeControl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * @author 丁常磊
 * @date 2021/8/12 15:39
 */
@Service
public class TimeControlImpl implements TimeControl {

    @Autowired
    private DelaySender delaySender;

    public void submit(String targetRoutingKey, Object payload, long delaySeconds) {
        submit(null, targetRoutingKey, payload, delaySeconds);
    }

    public void submit(String targetRoutingKey, Object payload, Time time) {
        submit(null, targetRoutingKey, payload, time.toSeconds());
    }

    public void submit(String targetRoutingKey, Object payload, Date date) {
        submit(null, targetRoutingKey, payload, date);
    }

    public void submit(String targetExchange, String targetRoutingKey, Object payload, long delaySeconds) {
        TimeTask timeTask = new TimeTask();
        timeTask.setPayload(payload);
        timeTask.setExchange(targetExchange);
        timeTask.setRoutingKey(targetRoutingKey);
        //记录发起时间
        timeTask.setStartTime(System.currentTimeMillis());

        //记录结束时间
        timeTask.setEndTime(timeTask.getStartTime() + delaySeconds * 1000);

        trigger(timeTask);
    }

    public void submit(String targetExchange, String targetRoutingKey, Object payload, Time time) {
        submit(targetExchange, targetRoutingKey, payload, time.toSeconds());
    }

    public void submit(String targetExchange, String targetRoutingKey, Object payload, Date date) {
        TimeTask timeTask = new TimeTask();
        timeTask.setPayload(payload);
        timeTask.setExchange(targetExchange);
        timeTask.setRoutingKey(targetRoutingKey);
        timeTask.setStartTime(System.currentTimeMillis());
        timeTask.setEndTime(date.getTime());
        trigger(timeTask);
    }


    public void trigger(TimeTask timeTask) {

        long sec = calibrationTime(timeTask);

        if (sec == 0) {
            delaySender.sendOnTime(timeTask);
            return;
        }

        //i一定大于0且小于等于20
        int i = maxQueue(sec);

        //路由到指定队列
        delaySender.sendDelay(timeTask, i - 1);

    }

    /**
     * 校正时间
     * 以任务期望结束时间点和当前时间进行比对
     */
    private long calibrationTime(TimeTask timeTask) {
        long t = (timeTask.getEndTime() - System.currentTimeMillis()) / 1000;

        //如果计算出来为负数则立刻执行任务
        if (t < 0) {
            t = 0;
        }
        return t;
    }

    /**
     * 计算最大队列
     * @param sec
     * @return
     */
    private static int maxQueue(long sec) {
        int i = 0;
        while (true) {
            if (sec == 0||i==20) {
                return i;
            }
            sec = sec >> 1;
            i++;
        }
    }


}
